﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Caching;
using DTO;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace DAO
{

    public abstract class IData<T>
    {
        protected Cache _cache = HttpContext.Current.Cache;
        protected SQLData connec = null;
        protected String strAsc = " order by orderId desc ";
        protected String strSelect = "select * from ";
        protected static string stringPath = HttpContext.Current.Server.MapPath("~/log");
        protected static string myStringConnec = "";
        protected static double time_cache = 2;
        public IData()
        {

        }

        public IData(String m_connec)
        {
            connec = new SQLData(m_connec);
            myStringConnec = m_connec;
        }

        protected abstract int InsertOnSubmit(ref T item, int t);
        public virtual int InsertOnSubmit(ref T item)
        {
            return InsertOnSubmit(ref item, 0);
        }

        public virtual int UpdateOnSubmit(T item)
        {
            return InsertOnSubmit(ref item, 1);
        }

        public virtual int DeleteOnSubmit(T item)
        {
            return InsertOnSubmit(ref item, 2);
        }

        public virtual int StatusOnSubmit(T item)
        {
            return InsertOnSubmit(ref item, 3);
        }
        public abstract T GetItemById(T item);
        public abstract T GetItemById(Object id);
        public abstract T GetItem(IDataReader dr);
        public abstract List<T> GetAll();
        public virtual DataTable GetDataTable(String strSQL, CommandType commandType, params SqlParameter[] paramSql)
        {
            DataTable tbl = new DataTable();
            SqlConnection connection = connec.Connection;
            SqlCommand command = new SqlCommand { CommandType = commandType, CommandText = strSQL, Connection = connection };
            command.Parameters.AddRange(paramSql);
            connection.Open();
            using (SqlDataAdapter da = new SqlDataAdapter(command))
            {
                da.Fill(tbl);
                da.Dispose();
            }
            connection.Close();
            return tbl;
        }

        public virtual String Backup(String pathFile,String dataBaseName) {
            return connec.Backup(pathFile, dataBaseName);
        }

        public virtual String Restore(String pathFile, String databaseName)
        {
            return connec.Restore(pathFile, databaseName);
        }

        public virtual List<T> GetListParameter(String strSQL, CommandType commandType, params SqlParameter[] paramSql)
        {
            List<T> list = new List<T>();
            SqlConnection connection = connec.Connection;
            SqlCommand command = new SqlCommand();
            command.CommandType = commandType;
            command.CommandText = strSQL;
            command.Connection = connection;
            command.Parameters.AddRange(paramSql);
            connection.Open();
            SqlDataReader reader;
            using (reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {

                    try
                    {
                        list.Insert(0, GetItem(reader));
                    }
                    catch (Exception err)
                    {
                        LogFile.writing(stringPath, "log.txt", "IData",
                       " GetListParameter ", " " + strSQL + " : " + err.Message.ToString());
                    }
                }
                reader.Close();
            }
            connection.Close();
            return list;
        }

        public virtual DataTable GetDataTableCache(String strNameCache, int time, String strSQL, CommandType commandType, params SqlParameter[] paramSql)
        {
            DataTable tbl = new DataTable();
            if (_cache[strNameCache] == null)
            {
                tbl = GetDataTable(strSQL, commandType, paramSql);
                _cache.Insert(strNameCache, tbl, null, DateTime.MaxValue, TimeSpan.FromSeconds(time));
            }
            else
            {
                tbl = (DataTable)_cache[strNameCache];
            }
            return tbl;
        }

        public virtual T GetCacheByid(String strNameCache, int time, Object id)
        {
            T a;
            String s = strNameCache + id.ToString();
            if (_cache[s] == null)
            {
                a = GetItemById(id);
                _cache.Insert(s, a, null, DateTime.MaxValue, TimeSpan.FromSeconds(time));
            }
            else
            {
                a = (T)_cache[s];
            }
            a = GetItemById(id);
            return a;
        }

        public virtual List<T> GetListCache(String strNameCache, int time)
        {
            List<T> list = null;
            if (_cache[strNameCache] == null)
            {
                list = GetAll();
                _cache.Insert(strNameCache, list, null, DateTime.MaxValue, TimeSpan.FromSeconds(time));
            }
            else
            {
                list = (List<T>)_cache[strNameCache];
            }
            return list;
        }

        public virtual List<T> View(String strSQL, CommandType commandtype)
        {
            List<T> list = new List<T>();
            SqlConnection connection = connec.Connection;
            SqlCommand command = new SqlCommand();
            command.CommandType = commandtype;
            command.CommandText = strSQL;
            command.Connection = connection;
            connection.Open();
            SqlDataReader reader;
            using (reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    try
                    {
                        list.Insert(0, GetItem(reader));
                    }
                    catch (Exception err)
                    {
                        LogFile.writing(stringPath, "log.txt", "IData",
                       " View ", " " + strSQL + " : " + err.Message.ToString());
                    }
                }
                reader.Close();
            }
            connection.Close();
            return list;
        }

        public virtual String GetJsons(List<T> list)
        {
            var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
            String jsonResult = JsonConvert.SerializeObject(list, settings);            
            return jsonResult;
        }

        public virtual List<T> GetFind(String sProc, String value)
        {
            List<T> list = new List<T>();
            SqlConnection connection = connec.Connection;
            SqlCommand command = new SqlCommand();
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = sProc;
            command.Connection = connection;
            SqlParameter p = new SqlParameter();
            p.ParameterName = "@find";
            p.Value = value;
            command.Parameters.Add(p);
            connection.Open();
            SqlDataReader reader;
            using (reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    try
                    {
                        list.Insert(0, GetItem(reader));
                    }
                    catch 
                    {
                        
                    }
                }
                reader.Close();
            }
            connection.Close();
            return list;
        }

        public virtual List<T> GetAll(String strSQL, CommandType commandtype)
        {
            List<T> list = new List<T>();
            SqlConnection connection = connec.Connection;
            SqlCommand command = new SqlCommand();
            command.CommandType = commandtype;
            command.CommandText = strSQL;
            command.Connection = connection;
            connection.Open();
            SqlDataReader reader;
            using (reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    try
                    {
                        list.Insert(0, GetItem(reader));
                    }
                    catch (Exception err)
                    {
                        LogFile.writing(stringPath, "log.txt", "IData",
                       " GetAll ", " " + strSQL + " : " + err.Message.ToString());
                    }

                }
                reader.Close();
            }
            connection.Close();
            return list;

        }

    }
}
